/* *****************************************************************************************
 
Made by www.Flashphoner.com, all rights reserved.
These sources can only be used for working with Flashphoner server.
If you want use this to create your own application (separate from Flashphoner server) � 
please contact support@flashphoner.com 

******************************************************************************************/

package com.flashphoner.api
{	
	import com.adobe.cairngorm.control.CairngormEventDispatcher;
	import com.flashphoner.Logger;
	import com.flashphoner.api.data.Call;
	import com.flashphoner.api.data.ErrorCodes;
	import com.flashphoner.api.data.ModelLocator;
	import com.flashphoner.api.data.PhoneConfig;
	import com.flashphoner.api.management.PhoneSpeaker;
	import com.flashphoner.api.management.SoundControl;
	import com.flashphoner.api.management.VideoControl;
	
	import flash.events.*;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.net.Responder;
	
	import mx.controls.Alert;
	
	/**
	 * Media server outgoing communication class
	 * **/
	internal class PhoneServerProxy
	{			
		//output voice stream
		private static var outStream:NetStream;
		
		private var responder:Responder;
		private var nc:NetConnection;		
		
		public var hasDisconnectAttempt:Boolean;
		
		public static var sendVideo:Boolean = false;
		
		public var phoneSpeaker:PhoneSpeaker;
		
		public function PhoneServerProxy(responder:Responder)
		{		
			this.responder = responder;
			nc = new NetConnection();
			nc.objectEncoding = flash.net.ObjectEncoding.AMF0;
			nc.client = new PhoneCallback();
			phoneSpeaker = new PhoneSpeaker(nc);
		}
		
		public function sendDtmf(call:Call,dtmf:String){
			Logger.info("PhoneServerProxy.sendDtmf() "+dtmf);
			nc.call("sendDtmf",responder,dtmf,call.id);
		}
		
		public function call(visibleName:String,callee:String,isVideoCall:Boolean):void{
			Logger.info("PhoneServerProxy.call()");
			nc.call("call",responder,visibleName,callee,isVideoCall);
		}	
		
		public function hangup(call:Call):void{
			Logger.info("PhoneServerProxy.hangup() call.id: "+call.id);
			nc.call("hangup",null,call.id);
		}
		
		public function answer(call:Call,isVideoCall:Boolean):void{
			Logger.info("PhoneServerProxy.answer() call.id: "+call.id);
			nc.call("answer",null,call.id,isVideoCall);	
		}
		
		public function publish(call:Call):void{
			Logger.info("PhoneServerProxy.publish() call.id: "+call.id);			
			if (outStream==null){
				outStream = new NetStream(nc);
				outStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler);
				outStream.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus);									
				outStream.attachAudio(SoundControl.getInstance().getMicrophone());		
				
				if (PhoneConfig.VIDEO_ENABLED && sendVideo){	 
					outStream.attachCamera(VideoControl.getInstance().getCam());					 
				}		
				outStream.publish(Flash_API.getInstance().modelLocator.login+"_"+call.id);
			}					
		}
		
		public function isSendVideo(flag:Boolean):void{
			sendVideo = flag;
			if (outStream == null){
				return;
			}
			if (sendVideo && Flash_API.getInstance().currentCall != null && !Flash_API.getInstance().currentCall.isVideoCall){
				nc.call("updateCallToVideo",null,Flash_API.getInstance().currentCall.id);
			}
			if (PhoneConfig.VIDEO_ENABLED && sendVideo){
				outStream.attachCamera(VideoControl.getInstance().getCam());
			}
			if (!sendVideo){
				outStream.attachCamera(null);
			}		
		} 
		
		private function asyncErrorHandler(event: AsyncErrorEvent):void {
	    }
	    
	    private function onNetStatus(event : NetStatusEvent) : void{
		}
		
		public function unpublish(call:Call):void{			
			if (outStream!=null){				
				outStream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler);
				outStream.removeEventListener(NetStatusEvent.NET_STATUS,onNetStatus);		
				outStream.close();
				phoneSpeaker.stop();			
				outStream=null;
			}		
		}	
		
		public function login(username:String = null, password:String = null):int{			
			var modelLocator:ModelLocator = Flash_API.getInstance().modelLocator;
			var obj:Object = new Object();
			obj.registerRequired = PhoneConfig.REGISTER_REQUIRED;
			if (username == null && password == null){
				obj.mode = "click2call";
				modelLocator.mode="click2call";
			}else{
				modelLocator.mode="flashphoner";
				if (username.indexOf("sip:") != 0 || username.indexOf("@") < 4){
					return 1;
				}	
				username = username.substring(4);
				obj.login = username.substring(0,username.indexOf("@"));
				obj.password = password;
				obj.mode = "flashphoner";
				obj.sipProviderAddress = username.substring(username.indexOf("@")+1,username.indexOf(":"));
				obj.sipProviderPort = username.substring(username.indexOf(":")+1);
				
			}
			obj.visibleName = modelLocator.visibleName;
			nc.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);	
			nc.connect(PhoneConfig.SERVER_URL+"/"+PhoneConfig.APP_NAME,obj);
			return 0;			
		}
		
		public function disconnect():void {
			hasDisconnectAttempt = true;
			nc.close();
		}
		
		public function netStatusHandler(event : NetStatusEvent) : void
		{			
			var modelLocator:ModelLocator = Flash_API.getInstance().modelLocator;
			if(event.info.code == "NetConnection.Connect.Success")
			{
				Logger.info("NetConnection.Connect.Success");
				Flash_API.getInstance().apiNotify.notifyConnected();	
				CairngormEventDispatcher.getInstance().dispatchEvent(new MainEvent(MainEvent.CONNECTED,false,false));
								
			}else if(event.info.code == "NetConnection.Connect.Failed")
			{
				Logger.info("NetConnection.Connect.Failed");
				PhoneModel.getInstance().dropRegisteredTimer();
				Flash_API.getInstance().apiNotify.notifyError(ErrorCodes.CONNECTION_ERROR);
				hasDisconnectAttempt = false;
			}else if (event.info.code == 'NetConnection.Connect.Rejected')
			{
				Logger.info("NetConnection.Connect.Rejected");
				Alert.show("Too many users. Please try again later.");
				hasDisconnectAttempt = false;
			}else if (event.info.code == 'NetConnection.Connect.Closed')
			{				
				Logger.info("NetConnection.Connect.Closed");
				Flash_API.getInstance().apiNotify.notifyCloseConnection();
				SoundControl.getInstance().stopRingSound();
				modelLocator.logged = false;
				hasDisconnectAttempt = false;
				modelLocator.login = null;
				modelLocator.pwd = null;
			}		
		}	
		

	}
}